import log4js from 'koa-log4';
import fetch from 'node-fetch';
import crypto from 'crypto';
import queryString from 'querystring';
import config from '../config';

const {
  ADMIN_GET_ME_URL,
  TEACHER_GET_ME_URL,
  CUSTOMER_MESSAGE_API_URL,
  CUSTOMER_MESSAGE_API_KEY,
} = config;
const getMeUrls = {
  teacher: TEACHER_GET_ME_URL,
  admin: ADMIN_GET_ME_URL,
};
const ApiBridgeLogger = log4js.getLogger('ApiBridge');

class ApiBridge {
  async doFetch(url, options = {}) {
    const res = await fetch(url, options);

    if (!res.ok) {
      const body = await res.text();
      throw new Error(body);
    } else {
      return res;
    }
  }

  async sendWeChatMessage({ content, type, toSocialId }) {
    try {
      const res = await this.doFetch(`${CUSTOMER_MESSAGE_API_URL}internal/messages/kf/incoming`, {
        method: 'POST',
        body: JSON.stringify({
          type,
          content,
          socialId: toSocialId,
        }),
        headers: {
          apikey: CUSTOMER_MESSAGE_API_KEY,
          'Content-Type': 'application/json',
        },
      });
      const json = await res.json();
      if (!json.ok) throw new Error(JSON.stringify(json));
    } catch (e) {
      ApiBridgeLogger.error(
        `Push Message To WeChat Fail with openId ${toSocialId} type ${type}`,
        e,
      );
      throw e;
    }
  }

  async getJiuQuUserByToken(token, role) {
    let userInfo = {};
    const getMeUrl = getMeUrls[role];
    if (!getMeUrl) return userInfo;

    try {
      const res = await this.doFetch(getMeUrl, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${token}`,
        },
      });
      userInfo = await res.json();
    } catch (e) {
      ApiBridgeLogger.error('Fetch User By Token: %s Role: %s with reason', token, role, e.message);
      throw e;
    }

    return userInfo;
  }

  async sendMessageToSkynet(roomId, message, skynetUrlMessageEndpoint) {
    const LUA_MESSAGE_ID = 12345;

    try {
      await this.doFetch(skynetUrlMessageEndpoint, {
        method: 'POST',
        body: JSON.stringify({
          roomid: roomId,
          id: LUA_MESSAGE_ID,
          value: message,
        }),
        headers: { 'Content-Type': 'application/json' },
      });
    } catch (e) {
      ApiBridgeLogger.error('Push Message To Skynet Fail', e);
      throw e;
    }
  }

  async getBitRate(teacherId, studentId, beginAt, endAt, verbose) {
    const queryStatement = [];
    if (teacherId) {
      queryStatement.push(verbose
        ? `SELECT time, audio_in_bps, video_in_bps, audio_out_bps, video_out_bps, server FROM t_${teacherId} WHERE time > ${beginAt}ms and time < ${endAt}ms`
        : `SELECT time, audio_in_bps + video_in_bps as in_bps, audio_out_bps + video_out_bps as out_bps FROM t_${teacherId} WHERE time > ${beginAt}ms and time < ${endAt}ms`);
    }
    if (studentId) {
      queryStatement.push(verbose
        ? `SELECT time, audio_in_bps, video_in_bps, audio_out_bps, video_out_bps, server FROM s_${studentId} WHERE time > ${beginAt}ms and time < ${endAt}ms`
        : `SELECT time, audio_in_bps + video_in_bps as in_bps, audio_out_bps + video_out_bps as out_bps FROM s_${studentId} WHERE time > ${beginAt}ms and time < ${endAt}ms`);
    }

    if (queryStatement.length === 0) return [];
    const query = {
      db: 'janus_rt_data',
      q: queryStatement.join(';'),
    };
    const queryStr = queryString.stringify(query);
    try {
      const response = await this.doFetch(`http://192.168.3.20:8086/query?${queryStr}`);
      return response.json();
    } catch (e) {
      ApiBridgeLogger.error('Fetch BitRate Fail', e);
      throw e;
    }
  }

  /**
   * @param {string} question 消息内容
   */
  async getMessageSuggestion(question) {
    const akKey = 'LTAIZySaabToUowO';
    const akSecret = '1fKHGUQ25Qpn4bm8fX4X94ehPQcVyK';
    const reqFields = {
      app_key: 'nui-N9HORrBOQEpZ',
      question,
      version: '3.0',
      optional: {
        top: 3,
      },
    };
    const md5Base64 = payload =>
      crypto
        .createHash('md5')
        .update(payload)
        .digest('base64');
    const sha1Base64 = payload =>
      crypto
        .createHmac('sha1', akSecret)
        .update(payload)
        .digest('base64');

    const nowGMT = new Date().toUTCString();
    const jsonBody = JSON.stringify(reqFields);
    const md5body = md5Base64(jsonBody);
    const strSign = `POST\napplication/json\n${md5body}\napplication/json\n${nowGMT}`;
    const signature = sha1Base64(strSign);

    try {
      const response = await this.doFetch('https://nlsapi.aliyun.com/qas', {
        method: 'POST',
        body: jsonBody,
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
          Date: nowGMT,
          Authorization: `Dataplus ${akKey}:${signature}`,
        },
      });
      return await response.json();
    } catch (e) {
      ApiBridgeLogger.error('Fetch Suggestion Error', e);
      throw e;
    }
  }
}

export default function init() {
  return new ApiBridge();
}
